package com.ruoyi.project.sdi.scan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.enums.BizType;
import com.ruoyi.common.enums.WorkloadType;
import com.ruoyi.common.utils.CommonParaTool;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.bms.bmsVoucherAssociate.domain.BmsVoucherAssociate;
import com.ruoyi.project.bms.bmsVoucherAssociate.service.IBmsVoucherAssociateService;
import com.ruoyi.project.er.domain.PaeaErError;
import com.ruoyi.project.er.enums.PaeaErrorSource;
import com.ruoyi.project.er.service.IPaeaErErrorRegisterService;
import com.ruoyi.project.sdi.scan.enums.AutoErrorDefine;
import com.ruoyi.project.sdi.scan.model.ScanSubmitReq;
import com.ruoyi.project.sdi.scan.service.IScanService;
import com.ruoyi.project.sdi.sdiImage.domain.SdiImage;
import com.ruoyi.project.sdi.sdiImage.service.ISdiImageService;
import com.ruoyi.project.sdi.sdiPaeaArc.domain.SdiPaeaArc;
import com.ruoyi.project.sdi.sdiPaeaArc.enums.ArchivePaeaStatus;
import com.ruoyi.project.sdi.sdiPaeaArc.service.ISdiPaeaArcService;
import com.ruoyi.project.stat.paeaReportWorkload.service.IStatisticsWorkloadService;
import com.ruoyi.project.system.user.domain.User;
import com.ruoyi.project.system.user.service.IUserService;
import com.ruoyi.project.tool.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 功能描述：
 *
 * @author 关晓强
 * @version 1.0
 * @date 2020/3/20 20:45
 */
@Service
@Slf4j
public class ScanServiceImpl implements IScanService {

    @Autowired
    private ISdiPaeaArcService sdiPaeaArcService;

    @Autowired
    private ISdiImageService sdiImageService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IBmsVoucherAssociateService bmsVoucherAssociateService;

    @Autowired
    private IPaeaErErrorRegisterService paeaErErrorRegisterService;

    @Autowired
    private IStatisticsWorkloadService statisticsWorkloadService;

    @Override
    @Transactional
    public boolean submit(ScanSubmitReq scanSubmitReq, User user) {

        // 首先判读批次是否已做过扫描，若是，则直接退出
        boolean isScaned = this.isScaned(scanSubmitReq.getTrDate(),scanSubmitReq.getOrgCode(),scanSubmitReq.getTellerCode());
        if (isScaned) {
            return false;
        }
        SdiPaeaArc sdiPaeaArc = createSdiPaeaArcByScanSubmitData(scanSubmitReq, user);
        // 插入sdiPaeaArc
        this.sdiPaeaArcService.save(sdiPaeaArc);
        List<SdiImage> sdiImages = Lists.newArrayList();
        for (int i = 0; i < scanSubmitReq.getFileNames().length; i += 2) {
            // 创建一条影像记录
            SdiImage sdiImage = createSdiImage(scanSubmitReq.getFileNames()[i],
                    sdiPaeaArc, i / 2 + 1, false);
            sdiImage.setSdifilepathL(scanSubmitReq.getFileNames()[i + 1]); // 背面地址
            sdiImages.add(sdiImage);
            sdiImage.setArcId(sdiPaeaArc.getId());
        }

        // 插入sdiImages
        sdiImageService.saveBatch(sdiImages);

        // 更新批次的登记信息
        BmsVoucherAssociate bmsVoucherAssociate = this.bmsVoucherAssociateService.getOne(new QueryWrapper<BmsVoucherAssociate>()
                .eq("tr_date",sdiPaeaArc.getTrDate())
                .eq("org_code",sdiPaeaArc.getOrgCode())
                .eq("teller_code",sdiPaeaArc.getTellerCode())
                .eq("be",1));
        if(bmsVoucherAssociate==null) {
            return false;
        }
        bmsVoucherAssociate.setScanStatus(1);
        bmsVoucherAssociate.setScanNum(sdiImages.size());
        this.bmsVoucherAssociateService.updateBmsVoucherAssociate(bmsVoucherAssociate);

        // 创建差错
        String errorMessage = scanSubmitReq.getErrorMessage();
        if (StringUtils.isNotEmpty(errorMessage)) {
            this.createScanError(scanSubmitReq,user);
        }
        // 记录工作量
        Date scanDate = new Date(System.currentTimeMillis());
        this.statisticsWorkloadService.writePaeaReportWorkload(user,scanDate,WorkloadType.扫描,scanSubmitReq.getFileNames().length,user.getDeptId());
        // 提交完 清除数据
        sdiPaeaArc = null;
        sdiImages.clear();
        sdiImages = null;
        return true;
    }

    /**
     * 创建扫描差错
     * @param scanSubmitReq
     * @param user
     */
    private void createScanError(ScanSubmitReq scanSubmitReq,User user) {
        PaeaErError paeaErError = new PaeaErError();
        paeaErError.setCreateBy(user.getUserId());
        paeaErError.setCreateTime(new Date());
        paeaErError.setErrSource(PaeaErrorSource.S凭证扫描.getValue());
        paeaErError.setTrDate(new java.sql.Date(scanSubmitReq.getTrDate().getTime()));
        paeaErError.setOrgId(scanSubmitReq.getOrgCode());
        paeaErError.setTellerId(scanSubmitReq.getTellerCode());
        List<String> paeaErPoints = Lists.newArrayList(AutoErrorDefine.扫描风险点.getPaeaErTypeCode(),AutoErrorDefine.扫描风险点.getErrorPoint());
        paeaErError.setPaeaErPointIds(paeaErPoints);
        paeaErError.setAuditProceeding(scanSubmitReq.getErrorMessage());
        Date correctLimitDate = CommonParaTool.getCorrectLimitDate();
        paeaErError.setCorrectLimitDate(new java.sql.Date(correctLimitDate.getTime()));
        this.paeaErErrorRegisterService.registerError(paeaErError);
        log.info("日期：" + scanSubmitReq.getTrDate() + " 机构：" + scanSubmitReq.getOrgCode() + " 柜员："
                + scanSubmitReq.getTellerCode() + " 风险信息：" + scanSubmitReq.getErrorMessage());
    }

    /**
     * 通过扫描提交数据创建批次
     *
     * 说明：批次状态修改为200（待OCR识别）
     * @param scanSubmitReq
     * @return
     */
    private SdiPaeaArc createSdiPaeaArcByScanSubmitData(ScanSubmitReq scanSubmitReq, User user) {
        {
            SdiPaeaArc sdiPaeaArc = new SdiPaeaArc();
            sdiPaeaArc.setCapturer(ShiroUtils.getUserId());
            sdiPaeaArc.setCaptureTime(new Date());
            String code = DateTimeUtil.shortFmt(scanSubmitReq.getTrDate(),DateTimeUtil.FMT_YYMMDD) + "-" + scanSubmitReq.getOrgCode() + "-"
                    + scanSubmitReq.getTellerCode() + "-" + user.getUserId() + "-01";
            sdiPaeaArc.setCode(code);
            sdiPaeaArc.setCreateor(user.getUserId());
            sdiPaeaArc.setCreateTime(new Date());
            sdiPaeaArc.setDocNum(0);
            sdiPaeaArc.setFrontNum(0);
            sdiPaeaArc.setImageNum(scanSubmitReq.getFileNames().length);
            sdiPaeaArc.setFrontNum(scanSubmitReq.getFileNames().length / 2);
            sdiPaeaArc.setIndexNo(Integer.parseInt(sdiPaeaArc.getCode().substring(
                    sdiPaeaArc.getCode().length() - 2)));
            sdiPaeaArc.setOrgCode(scanSubmitReq.getOrgCode());
            sdiPaeaArc.setTellerCode(scanSubmitReq.getTellerCode());
            sdiPaeaArc.setParentId(scanSubmitReq.getParentId());
            sdiPaeaArc.setTrDate(scanSubmitReq.getTrDate());

            sdiPaeaArc.setStatus(ArchivePaeaStatus.WaitOcr.getValue());
            sdiPaeaArc.setLocker("-1");
            sdiPaeaArc.setAuditOrgCode(user.getDeptId());
            sdiPaeaArc.setInputOrgCode(user.getDeptId());
            return sdiPaeaArc;
        }
    }

    /**
     * 判断批次是否已扫描
     * @param trDate
     * @param orgCode
     * @param tellerCode
     * @return
     */
    @Override
    public boolean isScaned(Date trDate, String orgCode, String tellerCode) {
        SdiPaeaArc sdiPaeaArc = this.sdiPaeaArcService.getOne(new QueryWrapper<SdiPaeaArc>()
                .eq("tr_date",trDate)
                .eq("org_code",orgCode)
                .eq("teller_code",tellerCode)
                .ge("status", ArchivePaeaStatus.WaitOcr.getValue()));
        if(sdiPaeaArc!=null){
            return true;
        }
        return false;
    }

    /**
     * 补扫批次提交
     * @param scanSubmitReq
     * @param user
     * @return
     */
    @Override
    @Transactional
    public boolean submitAdd(ScanSubmitReq scanSubmitReq, User user) {

        SdiPaeaArc sdiPaeaArc = this.sdiPaeaArcService.getById(scanSubmitReq.getArcId());
        //保存补扫的时间
        // todo 缺票登记相关
//        java.sql.Date smTime = new java.sql.Date(System.currentTimeMillis());
//        String sql = "select entity from PaeaLostVoucher entity where entity.orgCode=? and entity.tellerCode=? and entity.trDate=?";
//        Object[] args=new Object[]{sdiPaeaArc.getOrgCode(),sdiPaeaArc.getTellerCode(),sdiPaeaArc.getTrDate()};
//        List<PaeaLostVoucher> paeaLostVouchers = (List<PaeaLostVoucher>)(List)servicePaeaLostVoucherImpl.findPaeaLostVouchersByHqls(sql,args);
//        for(int i = 0;i < paeaLostVouchers.size() ;i++ ){
//            PaeaLostVoucher paeaLostVoucher= paeaLostVouchers.get(i);
//            paeaLostVoucher.setSmTime(smTime);
//            servicePaeaLostVoucherImpl.updatePaeaLostVoucher(paeaLostVoucher);
//        }

        //补扫后批次回退正在重新补录795
        if(sdiPaeaArc.getStatus()==ArchivePaeaStatus.Complete.getValue()){//若批次已归档，需要回退到待手工补录
            //sdiPaeaArc.setStatus(ArchivePaeaStatus.待重新补录790.getValue());
            sdiPaeaArc.setStatus(ArchivePaeaStatus.正在重新补录795.getValue());
            //判断用户状态
            User preInputUser = userService.selectUserByLoginName(sdiPaeaArc.getInputer());
            if(preInputUser == null || !UserConstants.NORMAL.equals(preInputUser.getStatus())){
                //用户不存在或为停用，退回至待获取状态
                sdiPaeaArc.setLocker("-1");
                sdiPaeaArc.setStatus(ArchivePaeaStatus.待重新补录790.getValue());
                sdiPaeaArc.setPreviousInputer(sdiPaeaArc.getInputer());
            } else {
                //存在并生效状态，退回至已获取状态
                sdiPaeaArc.setLocker(sdiPaeaArc.getInputer());
                sdiPaeaArc.setPreviousInputer(sdiPaeaArc.getInputer());
            }
        }
        Integer maxCode = sdiPaeaArc.getImageNum();
        List<SdiImage> sdiImages = new ArrayList<>();
        SimpleDateFormat f = new SimpleDateFormat("yyyyMMdd");
        String[] fileNames = scanSubmitReq.getFileNames();
        for (int i = 0; i < fileNames.length; i += 2) {

            String fileName = fileNames[i];
            SdiImage sdiImage = this.createSdiImage(fileName, sdiPaeaArc,
                    ++maxCode, true);
            if (i % 2 == 0) { // 正面
                sdiImage.setSdifilepathL(fileNames[i + 1]);
            }
            sdiImage.setArcId(sdiPaeaArc.getId());
            sdiImages.add(sdiImage);
        }
        // 更新批次对应影像数量
        sdiPaeaArc.setImageNum(sdiPaeaArc.getImageNum() + fileNames.length);
        // 更新批次正面影像数量
        sdiPaeaArc.setFrontNum(sdiPaeaArc.getFrontNum() + fileNames.length / 2);
        // 柜员号小于六位，修改批次状态到重新补录
        if (sdiPaeaArc.getTellerCode().trim().length() < 6) {
            sdiPaeaArc.setStatus(ArchivePaeaStatus.toArcBatchStatus(
                    sdiPaeaArc.getStatus()).getAfterReScanStatus().getValue());
        }
        //设置批次补扫待重新补录
        sdiPaeaArc.setName("needReInput");
        // 更新sdiPaeaArc
        this.sdiPaeaArcService.updateById(sdiPaeaArc);
        // //插入sdiImages
        sdiImageService.saveBatch(sdiImages);
        // 更新批次补登信息
        BmsVoucherAssociate bmsVoucherAssociate = this.bmsVoucherAssociateService.getOne(new QueryWrapper<BmsVoucherAssociate>()
                .eq("tr_date",sdiPaeaArc.getTrDate())
                .eq("org_code",sdiPaeaArc.getOrgCode())
                .eq("teller_code",sdiPaeaArc.getTellerCode())
                .eq("be",2));
        if(bmsVoucherAssociate==null) {
            return false;
        }
        bmsVoucherAssociate.setScanStatus(1);
        bmsVoucherAssociate.setScanNum(sdiImages.size());
        this.bmsVoucherAssociateService.updateBmsVoucherAssociate(bmsVoucherAssociate);

        // 记录工作量
        Date scanDate = new Date(System.currentTimeMillis());
        this.statisticsWorkloadService.updatePaeaReportWorkloadAdd(user,scanDate,WorkloadType.扫描,fileNames.length);

        return true;
    }

    /**
     * 功能描述：创建影像
     *
     */
    private SdiImage createSdiImage(String fileName, SdiPaeaArc sdiPaeaArc,
                                    int seqNo, boolean isRescan) {
         SdiImage sdiImage = new SdiImage();
//        SdiImage sdiImage = this.serviceSdiImageImpl.createSdiImage(sdiPaeaArc
//                .getTrDate());
        sdiImage.setCode(sdiPaeaArc.getCode() + "-" + (seqNo));
        sdiImage.setBusinessType(BizType.PAB_BOS.getCode());
        sdiImage.setCreateDate(new Date());
        sdiImage.setDescription(null);
        sdiImage.setAuditOrgCode(sdiPaeaArc.getAuditOrgCode());
        sdiImage.setImageDigest(null);
        sdiImage.setIndexNo(seqNo);
        sdiImage.setTrDate(sdiPaeaArc.getTrDate());
        sdiImage.setIsFrontPage(true); // 只保存正面记录
        sdiImage.setName(fileName.substring(fileName.length() - 12));
        sdiImage.setIsPiece(false);
        sdiImage.setPageIndex(null);
        sdiImage.setStatus(isRescan?9:0);
        sdiImage.setSdifilepath(fileName);
        sdiImage.setSdifilepathL(fileName);
        return sdiImage;
    }

}
